package com.aliyun.heiyu.powermaster.server.service;

import com.aliyun.heiyu.common.util.StringUtil;
import com.aliyun.heiyu.common.util.TimeConvertUtil;
import com.aliyun.heiyu.powermaster.proto.*;
import com.aliyun.heiyu.powermaster.server.Error;
import com.aliyun.heiyu.powermaster.server.annotation.Transactional;
import com.aliyun.heiyu.powermaster.server.dao.DeviceAirDao;
import com.aliyun.heiyu.powermaster.server.dao.DeviceServerDao;
import com.aliyun.heiyu.powermaster.server.dao.WarningDao;
import com.aliyun.heiyu.powermaster.server.dao.entity.StateGridCollectInfoEntity;
import com.aliyun.heiyu.powermaster.server.dao.entity.WarningEntity;
import com.aliyun.heiyu.powermaster.server.dao.enums.WarningTypeEnum;
import com.aliyun.heiyu.powermaster.server.dao.impl.DeviceAirDaoImpl;
import com.aliyun.heiyu.powermaster.server.dao.impl.DeviceServerDaoImpl;
import com.aliyun.heiyu.powermaster.server.dao.impl.WarningDaoImpl;
import com.aliyun.heiyu.powermaster.server.factory.MasterThreadFactory;
import com.aliyun.heiyu.powermaster.server.obj.po.NewestAirPO;
import com.aliyun.heiyu.powermaster.server.obj.po.VerifyEdgePO;
import com.aliyun.heiyu.powermaster.server.util.ZkClientUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class WarningServiceImpl implements WarningService {
private static Logger LOGGER = LoggerFactory.getLogger(WarningServiceImpl.class);

    private WarningDao dao;

    private DeviceAirDao deviceAirDao;

    private DeviceServerDao deviceServerDao;

    private  WarningDao warningDao;


    public WarningServiceImpl() {
        this.dao = new WarningDaoImpl();
        this.deviceAirDao = new DeviceAirDaoImpl();
        this.warningDao = new WarningDaoImpl();
        this.deviceServerDao =new DeviceServerDaoImpl();
        scanning();
    }

    //告警监控功耗
    public void scanning() {
        ThreadPoolExecutor executorService = new ThreadPoolExecutor(1, 1,
            60, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(), new MasterThreadFactory("warning-monitoring"));
        executorService.execute(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    if(!ZkClientUtil.checkLeader()) {
                        return;
                    }
                    //获取最近一条功耗数据
                    Map<String, String> currentOnePower = dao.findCurrentOnePower();
                    Map<String, String> setAlarmLevel = dao.findSetAlarmLevel();
                    String result = setAlarmLevel.get("set_alarm_level");
                    if (StringUtil.isEmpty(result)) {
                        result = "1";
                    }
                    Integer level = Integer.valueOf(result);
                    if (null != currentOnePower && currentOnePower.size() != 0) {
                        String serverSn = currentOnePower.get("server_sn");
                        String serverPower = currentOnePower.get("server_power");
                        String cpuUsage = currentOnePower.get("cpu_usage");
                        if (!StringUtil.isEmpty(serverSn)) {
                            if (StringUtil.isEmpty(serverPower)) {
                                insert(serverSn, WarningTypeEnum.SERVER_POWER_NULL_ALARM.getDesc(), "警告,服务器功耗采集异常,采集到数据为空值", "server",4);
                            }
                            if (StringUtil.isEmpty(cpuUsage)) {
                                insert(serverSn, WarningTypeEnum.SERVER_CPU_NULL_ALARM.getDesc(), "警告,服务器cpu使用率采集异常,采集到cpu使用率为空值", "server",4);
                            }
                            double usage = new BigDecimal(cpuUsage).doubleValue();
                            if (usage > 80 && level <= 3) {
                                insert(serverSn, WarningTypeEnum.SERVER_CPU_HIGH_ALARM.getDesc(), "警告,服务器cpu使用率过高,cpu使用率大于80%", "server",3);
                            }
                            if (usage < 5 && level <= 1) {
                                insert(serverSn, WarningTypeEnum.SERVER_CPU_LOW_ALARM.getDesc(), "服务器cpu使用率过低,cpu使用率低于5%", "server",1);
                            }
                            int power = new BigDecimal(serverPower).intValue();
                            if (power > 400 && level <= 3) {
                                insert(serverSn, WarningTypeEnum.SERVER_POWER_HIGH_ALARM.getDesc(), "警告,服务器使用功耗过高,功耗大于400", "server",3);
                            }
                            if (power < 100 && level <= 2) {
                                insert(serverSn, WarningTypeEnum.SERVER_POWER_LOW_ALARM.getDesc(), "警告,服务器使用功耗略低,功耗小于100", "server",2);
                            }
                        }
                    }

                    try {
                        Thread.sleep(30 * 1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
    }

    @Override
    @Transactional
    public void insert(String equipmentNumber,String type,String content,String deviceType,Integer alarm_level) {
        //通过设备编号和类型查询
        WarningEntity byEqAndType = dao.findByEqAndType(equipmentNumber, type);
        if(null == byEqAndType){
            WarningEntity entity=new WarningEntity();
            entity.setContent(content);
            entity.setEquipmentNumber(equipmentNumber);
            entity.setTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
            entity.setType(type);
            entity.setState("2");
            entity.setDeviceType(deviceType);
            entity.setAlarm_level(alarm_level);
            boolean insert = dao.insert(entity);
            if(!insert){
                LOGGER.error("insert warning failed ");
            }
        }else {
            dao.updateWarningTime(byEqAndType.getId());
        }
    }



    @Override
    public List<WarningData> findAll(String state) {
        List<WarningData> resultList=new ArrayList<WarningData>();
        //查询所有告警数据
        List<WarningEntity> list = dao.findAll(state);
        if(null == list || list.size() == 0){
            return resultList;
        }
        for (WarningEntity entity :list) {
            String deviceType = entity.getDeviceType();
            if(null == deviceType){
                deviceType="";
            }

            String time = TimeConvertUtil.mysqlTimeSubstring(entity.getTime());
            String repairTime = TimeConvertUtil.mysqlTimeSubstring(entity.getRepairTime());
            WarningData warningData = WarningData.newBuilder().setId(entity.getId()).setState(entity.getState()).setEquipmentNumber(entity.getEquipmentNumber())
                .setContent(entity.getContent()).setTime(time).setType(entity.getType()).setDeviceType(deviceType)
                .setRepairTime(repairTime).setAlarmLevel(String.valueOf(entity.getAlarm_level())).build();

            resultList.add(warningData);
        }
        return resultList;
    }


    @Override
    public WarningEntity findOne(Integer id) {
        WarningEntity entity = dao.findOne(id);
        if(entity == null){
            return null;
        }
        return entity;
    }

    @Override
    public int findWarningCount() {
        Map<String, String> warningCount = dao.findWarningCount();
        if (null==warningCount||warningCount.size()==0){
            return 0;
        }
        String str = warningCount.get("count");
        int count = Integer.valueOf(str);
        return count;
    }

    @Override
    public GetAlarmLevelReply getAlarmLevel(GetAlarmLevelRequest request) {
        GetAlarmLevelReply.Builder builder = GetAlarmLevelReply.newBuilder();
        Map<String, String> setAlarmLevel = dao.findSetAlarmLevel();
        String result = setAlarmLevel.get("set_alarm_level");
        if (StringUtil.isEmpty(result)) {
            result = "1";
        }
        return builder.setAlarmLevel(result).build();
    }

    @Override
    public UpdateAlarmLevelReply updateAlarmLevel(UpdateAlarmLevelRequest request) {
        UpdateAlarmLevelReply.Builder builder = UpdateAlarmLevelReply.newBuilder();
        String alarmLevel = request.getAlarmLevel();
        if (StringUtil.isEmpty(alarmLevel)) {
            return builder.setErrCode(620).setErrMsg("参数异常").build();
        }
        boolean bool = dao.updateSetAlarmLevel(alarmLevel);
        if (!bool) {
            return  builder.setErrCode(621).setErrMsg("设置失败").build();
        }
        return builder.setErrCode(Error.SUCCESS.getCode()).setErrMsg(Error.SUCCESS.getMessage()).build();
    }

    @Override
    public PowerMonitoringReply powerMonitoring() {
        PowerMonitoringReply.Builder builder=PowerMonitoringReply.newBuilder();
        List<StateGridCollectInfoEntity> maxServer = dao.findMaxServer();
        int count = 0;
        System.out.println(maxServer);
        if(null == maxServer || maxServer.size() == 0) {
            return builder.setErrCode(530).setErrMsg("读取数据错误").build();
        }
        Set<String> sn = new HashSet<>();

        for (StateGridCollectInfoEntity entity :maxServer) {
            if (5 == count) {
                break;
            }
            String serverSn= entity.getServer_sn();
            if (sn.contains(serverSn) || StringUtil.isEmpty(serverSn)) {
                continue;
            }
            int power = 0;
            BigDecimal serverPower = entity.getServer_power();
            if (null != serverPower) {
                power = serverPower.intValue();
            }
            builder.addData(PowerMonitoring.newBuilder().setSn(serverSn).setPower(power).build());
            sn.add(serverSn);
            count ++;
        }
        return builder.build();
    }

    /**监控设备空调温度上限下限，和服务器功耗上限*/
    @Override
    public boolean verifyEdge(VerifyEdgePO po) {
        //获取告警级别
        Map<String, String> setAlarmLevel = warningDao.findSetAlarmLevel();
        String result = setAlarmLevel.get("set_alarm_level");
        Integer level =0;
        if(StringUtils.isNotBlank(result)){
             level =Integer.valueOf(result);
        }
        BigDecimal upperLimit =new BigDecimal(0);
        BigDecimal lowerLimit=new BigDecimal(0);

        BigDecimal value=new BigDecimal(0);

        if(StringUtils.isBlank(po.getMaxValue())){
            po.setMaxValue("0");
        }
        //空调
        if(po.getType().equals(1)){
            NewestAirPO newestAirPO = deviceAirDao.selectNewestAir();
            if(StringUtils.isBlank(newestAirPO.getLowerLimit())){
                newestAirPO.setLowerLimit("0");
            }
            if(StringUtils.isBlank(newestAirPO.getUpperLimit())){
                newestAirPO.setUpperLimit("0");
            }
            if(StringUtils.isBlank(po.getValue())){
                po.setMinValue("0");
            }
            upperLimit = new BigDecimal(newestAirPO.getUpperLimit());
            lowerLimit = new BigDecimal(newestAirPO.getLowerLimit());
            value = new BigDecimal(po.getValue());
            if(value.compareTo(upperLimit) == 1){
                boolean warn = existWarn(newestAirPO.getDeviceId(),WarningTypeEnum.AIR_CONDITIONING_SETTING_TEMPERATURE_UPPER_LIMIT_ALARM.getDesc());
                if(warn){
                    return false;
                }
                // 这里开始预警
                WarningEntity entity = new WarningEntity();
                entity.setEquipmentNumber(newestAirPO.getDeviceId());
                entity.setTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
                entity.setType(WarningTypeEnum.AIR_CONDITIONING_SETTING_TEMPERATURE_UPPER_LIMIT_ALARM.getDesc());
                entity.setContent("空调设置温度过高，上限温度为:"+upperLimit+",当前设置温度为:"+value);
                entity.setState("2");
                entity.setDeviceType("air");
                entity.setAlarm_level(2);
                if(2>=level){
                    warningDao.insert(entity);
                }
                return false;
            }

            if(lowerLimit.compareTo(value) == 1){
                boolean warn = existWarn(newestAirPO.getDeviceId(),WarningTypeEnum.AIR_CONDITIONER_SETTING_TEMPERATURE_LOWER_LIMIT_ALARM.getDesc());
                if(warn){
                    return false;
                }
                // 这里开始预警
                WarningEntity entity = new WarningEntity();
                entity.setEquipmentNumber(newestAirPO.getDeviceId());
                entity.setTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
                entity.setType(WarningTypeEnum.AIR_CONDITIONER_SETTING_TEMPERATURE_LOWER_LIMIT_ALARM.getDesc());
                entity.setContent("空调设置温度过低，下限温度为:"+lowerLimit+"，当前设置温度为:"+value);
                entity.setState("2");
                entity.setDeviceType("air");
                if(2>=level) {
                    entity.setAlarm_level(2);
                    warningDao.insert(entity);
                }
                return false;
            }
        }
        //服务器
        else if(po.getType().equals(2)){
            //判断该类型未修复的是否存在
            boolean warn = existWarn(po.getDeviceId(),WarningTypeEnum.SERVER_PREDICTED_POWER_CONSUMPTION_UPPER_LIMIT_ALARM.getDesc());
            if(warn){
                return false;
            }
           String  serverUpperLimit = deviceServerDao.selectForecastPowerUpperLimit(po.getDeviceId());
           if(StringUtils.isBlank(serverUpperLimit)){
               serverUpperLimit="0";
           }
            upperLimit=new BigDecimal(serverUpperLimit);
            value = new BigDecimal(po.getValue());
            if(value.compareTo(upperLimit) == 1){
                // 这里开始预警
                WarningEntity entity = new WarningEntity();
                entity.setEquipmentNumber(po.getDeviceId());
                entity.setTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
                entity.setType(WarningTypeEnum.SERVER_PREDICTED_POWER_CONSUMPTION_UPPER_LIMIT_ALARM.getDesc());
                entity.setContent("服务器预测功耗过高，预测功耗上限为:"+upperLimit+"，当前预测功耗为:"+value);
                entity.setState("2");
                entity.setDeviceType("server");
                entity.setAlarm_level(2);
                if(2>=level) {
                    warningDao.insert(entity);
                }
                return false;
            }
        }
        return true;
    }

    /**
     * 判断是否存在该类型的告警数据
     * @param type
     * @param sn
     * @return
     */
    @Override
    public boolean existWarn(String sn,String type) {
       return warningDao.existWarn(sn,type);
    }


    @Override
    @Transactional
    public void update(UpdateWarningRequest request){
        boolean update = dao.update(request.getId(), request.getState());
        if(!update){
            LOGGER.error("update warning failed warningID = {}",request.getId() );
            throw new RuntimeException("update warning failed, warningID: " + request.getId());
        }
    }


}
